require "lfs"
require "luaMPI"
local nl = require'luaNumeric'
local unity = require "unity";

local FDTDSolver={
     get_settings_str = Gallop.get_settings_str;
     set_settings_str = Gallop.set_settings_str; 
};

----------------------------------------------------------------------------------------------------------------------------------------
--创建表和创建元表
function FDTDSolver:new (o)
	o = o or {};
	self.__index = self;
	setmetatable(o,self)
	return o;
end
----------------------------------------------------------------------------------------------------------------------------------------


-----------------------------------------------------------------------------
--运行
function FDTDSolver:runSolver ()
	-- print( 'suspend:',GetSuspendFlag())
	print( 'Run ... ' )
	if GetSuspendFlag() ~= true then 
		assert( Geometry.get_project_path() ~='' , '请先保存工程文件');
		Geometry.Solver.pre_calculate()	
	end
	
	local max_steps = Geometry.Solver.max_steps();
	local stride  = 50;
	local accuracy = Geometry.Solver.accuracy()
		
	 for ii=1,max_steps/stride do
	 	--print( 'step' )

		 if( Geometry.Solver.is_convergent(accuracy) ) then
			 break;
		 end
		 Geometry.Solver.steps( stride )
	 end

	print ( "Iteration finished..." )
	Geometry.Solver.stop()

	print ( "Stop solver, and start post calculation ..." )
	self:postRunSolver()

end
-----------------------------------------------------------------------------


-----------------------------------------------------------------------------
--停止
function FDTDSolver:stopSolver ()
	print ( "Stop solver ..." )
	Geometry.Solver.stop()
	print ( "Post calculation ..." )
	self:postRunSolver()
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--运行
function FDTDSolver.suspendSolver ()

end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--后处理
function FDTDSolver.postRunSolver ()
	print( 'Post run, save summary file and probes to path: ', Geometry.get_project_path_utf8() );
	Geometry.save_summary((Geometry.get_project_path_utf8())..'-runinfo.log')
	local fbox = Geometry.farbox_list();
	if #fbox >= 1 then
		--print( unity.local_to_utf8((Geometry.get_project_path()))..'-rcs.dat', 'RCS(dBsm)' );
		fbox[1]:save( (Geometry.get_project_path_utf8())..'-rcs.dat', 'RCS(dBsm)' )
		fbox[1]:save( (Geometry.get_project_path_utf8())..'-'..fbox[1]:name()..'-efields.dat', 'E-Field' )
	end
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--获取所有计算结果
function FDTDSolver:getResults (k)
	local results = {};
	local pbs = Geometry.objects("probes");
	for kk,vv in pairs( pbs ) do 
		results[kk] = vv:copy();
	end
	return results;
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--设置所有计算结果
function FDTDSolver:setResults (res,k)
	local pbs = Geometry.objects("probes");
	assert( #pbs == #res, "probes dismatch" );
	if res ~= nil then
		Geometry.RemoveProbes();
		for kk,vv in pairs (res) do
			Geometry.AddProbe( vv )
		end
	end
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--保存计算结果到硬盘
function FDTDSolver:saveResults2Path (path, prefixName)
	local results = {};
	local pbs = Geometry.objects("probes");
	for kk,vv in pairs( pbs ) do 
		vv:save(path .. '/' .. prefixName .. '[name-(' .. vv:name() .. ')].txt');
		if vv:record_time_fields() then
			vv:save_fields_time(path .. '/' .. prefixName .. '[name-(' .. vv:name() .. ')-time_fields].txt');		
		end
	end
	return results;
end
-----------------------------------------------------------------------------


--=====================================================================--
--获取端口源的功率
function FDTDSolver:get_port_power (freq)
	local objs = Geometry.get_all_objects('','source');
	pout = 1;
	ptotal = 1;
	for k,v in pairs (objs) do 
		if v:shape_type()=='LumpedSrc' then
			local res = v:results();
			local vfreq = res.freq;
			local vpout = nl.abs(res.data['Pout (w)'])
			local vptotal = nl.abs(res.data['PTotal (w)'])
			pout = nl.interpolation(vfreq,vpout,freq);
			ptotal = nl.interpolation(vfreq,vptotal,freq);
		end
	end
	--print('Source power:',ptotal,pout);
	return ptotal,pout;
end
--=====================================================================--

--=====================================================================--
--获取所有集总端口源的功率
function FDTDSolver:get_all_lumpedsrc_ports_power (freq)
	local objs = Geometry.get_all_objects('','source');
	local pout = 0;
	local ptotal = 0;
	local numsrc = 0;
	for k,v in pairs (objs) do 
		if v:shape_type()=='LumpedSrc' then
			local res = v:results();
			local vfreq = res.freq;
			local vpout = nl.abs(res.data['Pout (w)'])
			local vptotal = nl.abs(res.data['PTotal (w)'])
			pout = pout+nl.interpolation(vfreq,vpout,freq);
			ptotal = ptotal+nl.interpolation(vfreq,vptotal,freq);
			numsrc = numsrc+1;
		end
	end
	--print('Source power:',ptotal,pout);
	if numsrc>0 then 
		return ptotal,pout;
	end
	return 1.,1.;
end
--=====================================================================--

return FDTDSolver;
